#ifndef MATH_POINT_H
#define MATH_POINT_H

#include <iostream>
#include <string>

#include "../Utilities.h"

namespace Math
{
	class Point
	{
		public:
				/** Default constructor. Prevents implicit conversion, such as Point p=3.0f; */
				explicit Point(float x=0.0f, float y=0.0f, float z=0.0f);
				Point(const Point& p);

				/**********
				* GETTERS *
				**********/

				float x() const;
				float y() const;
				float z() const;

				/**********
				* SETTERS *
				**********/

				void setX(float val=0.0f);
				void setY(float val=0.0f);
				void setZ(float val=0.0f);
				void setPosition(float valX=0.0f, float valY=0.0f, float valZ=0.0f);

				/**********
				* UTILITY *
				**********/
				std::string toString();

				/************
				* OPERATORS *
				************/

				/** Provide a + operator to support vector addition
				* Various syntactic elements and their benefits are explained in this tutorial:
				* http://www.cs.duke.edu/csed/tapestry/howtoe.pdf
				*/
				const Point& operator+= (const Point& p)
				{
					_x+=p.x();
					_y+=p.y();
					_z+=p.z();

					return *this;
				}

				const Point& operator-= (const Point& p)
				{
					_x-=p.x();
					_y-=p.y();
					_z-=p.z();

					return *this;
				}

				friend Point operator- (const Point& p1, const Point& p2)
				{
					Point result(p1);
					result-=p2;

					return result;
				}

				/** Provide a << operator for convenience */
				friend std::ostream& operator<< (std::ostream& output, const Point& p)
				{
					output << "("+getString<float>(p.x())+";"+getString<float>(p.y())+";"+getString<float>(p.z())+")";
					return output;
				}

		protected:

				float _x;
				float _y;
				float _z;
	};
}

#endif
